﻿using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace Ant.ICommon.Utilities
{
    public static class XmlHelper
    {
        /// <summary>
        /// 将对象序列化到指定文件
        /// </summary>
        /// <param name="filePath">序列化文件位置</param>
        /// <param name="value">需要序列化的对象</param>
        /// <param name="prefix"></param>
        /// <param name="ns"></param>
        public static void SerizlizerXml(string filePath, object value, string prefix, string ns)
        {
            XmlSerializer xmlSer = new XmlSerializer(value.GetType());
            XmlSerializerNamespaces serializerNamespaces = new XmlSerializerNamespaces();
            serializerNamespaces.Add(prefix, ns);
            using (StreamWriter sw = new StreamWriter(filePath))
            {
                xmlSer.Serialize(sw, value, serializerNamespaces);
                sw.Flush();
                sw.Close();
            }
        }

        /// <summary>
        /// 将对象序列化到指定文件
        /// </summary>
        /// <param name="filePath">序列化文件位置</param>
        /// <param name="value">需要序列化的对象</param>
        /// <param name="fileMode">打开文件方式。</param>
        /// <param name="serializerNamespaces">序列化命名空间</param>
        public static void SerizlizerXml(string filePath, object value, FileMode fileMode = FileMode.CreateNew, XmlSerializerNamespaces serializerNamespaces = null)
        {
            XmlSerializer xmlSer = new XmlSerializer(value.GetType());
            using (FileStream fs = new FileStream(filePath, fileMode))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    if (serializerNamespaces != null)
                        xmlSer.Serialize(sw, value, serializerNamespaces);
                    else
                        xmlSer.Serialize(sw, value);
                    sw.Flush();
                    sw.Close();
                }
            }
        }

        /// <summary>
        /// 从xml文件中反序列化成指定对象
        /// </summary>
        /// <typeparam name="T">指定对象的数据类型</typeparam>
        /// <param name="filePath">xml文件物理地址</param>
        /// <returns></returns>
        public static T DeserializeXml<T>(string filePath) where T : class, new()
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException(string.Format("文件：{0}不存在。", filePath), filePath);

            T obj = null;
            using (TextReader stream = new StreamReader(filePath))
            {
                obj = DeserializeXmlByTextReader<T>(stream);
            }
            return obj;
        }

        /// <summary>
        /// 从xml文本中反序列化成指定对象。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlText">Xml字符串。</param>
        /// <returns>指定对象类型。</returns>
        public static T DeserializeXmlText<T>(string xmlText) where T : class
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            T obj = null;
            using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlText)))
            {
                using (StreamReader streamReader = new StreamReader(memoryStream))
                {
                    obj = DeserializeXmlByTextReader<T>(streamReader);
                }
            }
            return obj;
        }

        /// <summary>
        /// 从xml字符串中反序列化成指定对象。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="textReader">文本流。</param>
        /// <returns>指定对象类型。</returns>
        public static T DeserializeXmlByTextReader<T>(TextReader textReader) where T : class
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            string xmlText = textReader.ReadToEnd();
            return (T)serializer.Deserialize(new StringReader(xmlText));
        }

        /// <summary>
        /// 从对象序列化成xml字符串
        /// </summary>
        /// <param name="value">对象</param>
        /// <param name="prefix"></param>
        /// <param name="ns"></param>
        /// <returns></returns>
        public static string GetSerizlizerXmlText(object value, string prefix, string ns)
        {
            string text = string.Empty;
            SerizlizerXmlTextReader(value, (stream) =>
            {
                text = UTF8Encoding.UTF8.GetString(stream.ToArray());
            }, prefix, ns);
            return text;
        }

        /// <summary>
        /// 对象序列化后的文本流。
        /// </summary>
        /// <param name="value">需要序列化的对象。</param>
        /// <param name="ac">执行的方法</param>
        /// <param name="prefix"></param>
        /// <param name="ns"></param>
        public static void SerizlizerXmlTextReader(object value, Action<MemoryStream> ac, string prefix, string ns)
        {
            XmlSerializer serializer = new XmlSerializer(value.GetType());
            XmlSerializerNamespaces serializerNamespaces = new XmlSerializerNamespaces();
            serializerNamespaces.Add(prefix, ns);
            using (MemoryStream stream = new MemoryStream())
            {
                serializer.Serialize(stream, value, serializerNamespaces);
                ac(stream);
            }
        }

        /// <summary>
        /// 获取对象序列化后的文本。
        /// </summary>
        /// <param name="value">需要序列化的对象。</param>
        /// <param name="serializerNamespaces">序列化命名空间。</param>
        public static string GetSerizlizerXmlText(object value, XmlSerializerNamespaces serializerNamespaces = null)
        {
            string text = string.Empty;
            SerizlizerXmlTextReader(value, (stream) =>
            {
                text = UTF8Encoding.UTF8.GetString(stream.ToArray());
            }, serializerNamespaces);
            return text;
        }

        /// <summary>
        /// 对象序列化后的文本流。
        /// </summary>
        /// <param name="value">需要序列化的对象。</param>
        /// <param name="ac">执行的方法。</param>
        /// <param name="serializerNamespaces">序列化命名空间。</param>
        public static void SerizlizerXmlTextReader(object value, Action<MemoryStream> ac, XmlSerializerNamespaces serializerNamespaces = null)
        {
            XmlSerializer serializer = new XmlSerializer(value.GetType());
            using (MemoryStream stream = new MemoryStream())
            {
                if (serializerNamespaces != null)
                    serializer.Serialize(stream, value, serializerNamespaces);
                else
                    serializer.Serialize(stream, value);
                ac(stream);
            }
        }
    }
}